<?php
/**
 * Created by PhpStorm.
 * User: 86151 - 姜伟
 * Date: 2022/9/5 11:25.
 */

namespace Xinyu\Gen\Core\Libs;

use Doctrine\DBAL\DriverManager;

class TableClient extends BaseClient
{
    use SingletonUtil;

    private $config;

    public function __construct()
    {
        $this->config = config('database.connections.' . config('database.default'));
    }

    // 获取表验证器信息
    public function getTableValidatorInfo($tableName = '', $unique = '', $except = '')
    {
        if (empty($tableName)) {
            return $this->error('表名称不能为空');
        }
        $columns = $this->getTableColumns($tableName);
        $validatorRule = '';
        $validatorAttributes = '';
        $filterFields = ValidatorClient::getInstance()->getFilterFields();
        $exceptList = empty($except) ? [] : explode(',', $except);
        $sceneAddParams = ''; // 添加的场景参数
        $sceneModifyParams = ''; // 编辑的场景参数
        $i = 1;
        $primaryKey = 'id'; // 主键
        foreach ($columns as $k => $column) {
            $isPrimaryKey = $column->getAutoincrement();
            $name = $column->getName();
            $nameIsExcept = in_array($name, $exceptList, true);
            if ($isPrimaryKey) {
                $primaryKey = $name;
            }
            if (in_array($name, $filterFields, true)) {
                continue;
            }
            $type = $column->getType()->getName();
            $comment = $column->getComment();
            $length = $column->getLength();
            $ruleType = ValidatorClient::getInstance()->getRuleType($type, $comment, $length);
            $intro = ValidatorClient::getInstance()->getIntro($name, $comment);
            // 处理唯一字段
            $uniqueList = explode(',', $unique);
            if (in_array($name, $uniqueList, true)) { // 是唯一字段
                $ruleTypes = explode('|', $ruleType);
                $uniqueRuleTypes = '';
                foreach ($ruleTypes as $uk => $uv) {
                    $uniqueRuleTypes .= ($uk ? str_repeat(' ', 16) : '') . "'{$uv}'," . PHP_EOL;
                }
                $uniqueRuleTypes = rtrim($uniqueRuleTypes, PHP_EOL);
                $validatorRule .= str_repeat(' ', 12) . "'{$name}@add' => [
                'required',
                {$uniqueRuleTypes}
                Rule::unique(self::\$model)
            ],
            '{$name}@modify' => [
                'required',
                {$uniqueRuleTypes}
                Rule::unique(self::\$model)->ignore(request()->{$primaryKey})
            ]," . PHP_EOL;
                $itemSceneAddParams = (1 === $i % 4 ? str_repeat(' ', 16) : '') . "'{$name}@add', ";
                if (0 === $i % 4) {
                    $itemSceneAddParams .= PHP_EOL;
                }
                !$nameIsExcept && $sceneAddParams .= $itemSceneAddParams;
                $itemSceneModifyParams = (1 === $i % 4 ? str_repeat(' ', 16) : '') . "'{$name}@modify', ";
                if (0 === $i % 4) {
                    $itemSceneModifyParams .= PHP_EOL;
                }
                if (!$nameIsExcept) {
                    $sceneModifyParams .= $itemSceneModifyParams;
                    $i++;
                }
            } else { // 不是唯一字段
                if ($isPrimaryKey) { // 主键
                    $intro = 'ID';
                    $validatorRule .= str_repeat(' ', 12) . "'{$name}' => 'required|{$ruleType}|exists:' . self::\$model," . PHP_EOL;
                } else {
                    $itemSceneActionParams = (1 === $i % 4 ? str_repeat(' ', 16) : '') . "'{$name}', ";
                    if (0 === $i % 4) {
                        $itemSceneActionParams .= PHP_EOL;
                    }
                    if (!$nameIsExcept) {
                        $sceneAddParams .= $itemSceneActionParams;
                        $sceneModifyParams .= $itemSceneActionParams;
                        $i++;
                    }
                    $validatorRule .= str_repeat(' ', 12) . "'{$name}' => 'required|{$ruleType}'," . PHP_EOL;
                }
            }
            $validatorAttributes .= str_repeat(' ', 12) . "'{$name}' => '{$intro}'," . PHP_EOL;
        }
        $validatorRule = rtrim($validatorRule, PHP_EOL);
        $validatorAttributes = rtrim($validatorAttributes, PHP_EOL);
        $sceneAddParams = rtrim($sceneAddParams, ' ');
        $sceneAddParams = rtrim($sceneAddParams, PHP_EOL);
        $sceneModifyParams = rtrim($sceneModifyParams, ' ');
        $sceneModifyParams = rtrim($sceneModifyParams, PHP_EOL);
        return [
            'scene_add_params' => $sceneAddParams,
            'scene_modify_params' => $sceneModifyParams,
            'validator_rule' => $validatorRule,
            'validator_attributes' => $validatorAttributes,
            'primary_key' => $primaryKey,
        ];
    }

    // 获取表Service信息
    public function getTableServiceInfo($tableName = '')
    {
        if (empty($tableName)) {
            return $this->error('表名称不能为空');
        }
        $columns = $this->getTableColumns($tableName);
        $filterFields = ValidatorClient::getInstance()->getFilterFields();
        $actionDataParams = ''; // 添加/编辑的操作参数
        $primaryKey = 'id'; // 主键
        $columnList = [];
        foreach ($columns as $k => $column) {
            $isPrimaryKey = $column->getAutoincrement();
            $name = $column->getName();
            $comment = $column->getComment();
            $type = $column->getType()->getName();
            $columnList[$name] = [
                'comment' => $comment,
                'type' => $type,
            ];
            if ($isPrimaryKey) {
                $primaryKey = $name;
            }
            if (in_array($name, $filterFields, true)) {
                continue;
            }
            if ($name !== $primaryKey) {
                $actionDataParams .= str_repeat(' ', 12) . "'{$name}' => \$params['{$name}']," . PHP_EOL;
            }
        }
        $actionDataParams = rtrim($actionDataParams, PHP_EOL);
        return [
            'action_data_params' => $actionDataParams,
            'primary_key' => $primaryKey,
            'column_list' => $columnList,
        ];
    }

    // 获取postman接口调试参数
    public function getPostmanRequestParams($params = [])
    {
        $tableName = $params['name'] ?? '';
        if (empty($tableName)) {
            return $this->error('表名称不能为空');
        }
        $search = $params['search'] ?? '';
        $searchList = empty($search) ? [] : explode(',', $search);
        $columns = $this->getTableColumns($tableName);
        $filterFields = ValidatorClient::getInstance()->getFilterFields();
        $actionParams = []; // 添加/编辑参数
        $actionDocParams = '{' . PHP_EOL; // 添加/编辑文档参数
        $listParams = ['page' => 1, 'pagesize' => 10]; // 分页列表参数
        $columnList = [];
        $realColumns = array_filter($columns, function ($column) use ($filterFields) {
            $name = $column->getName();
            return !in_array($name, $filterFields, true);
        });
        if (!empty($realColumns)) {
            $realColumnNum = count($realColumns);
            $columnIndex = 0;
            foreach ($realColumns as $k => $column) {
                $name = $column->getName();
                $comment = $column->getComment();
                $type = $column->getType()->getName();
                $columnList[$name] = [
                    'comment' => $comment,
                    'type' => $type,
                ];
                $value = PostmanClient::getInstance()->getValue($type);
                $actionParams[$name] = $value;
                if (is_string($value)) {
                    $value = '""';
                }
                $isEnd = $columnIndex === $realColumnNum - 1;
                $dh = !$isEnd ? ',' : '';
                $actionDocParams .= "    \"{$name}\": {$value}{$dh} // {$comment}" . PHP_EOL;
                $columnIndex++;
            }
        }
        $actionParams = json_encode($actionParams, JSON_UNESCAPED_UNICODE);
        $actionDocParams .= '}';
        $realSearchList = array_filter($searchList, function ($item) use ($columnList) {
            return isset($columnList[$item]);
        });
        $listDocParamsEndDh = !empty($realSearchList) ? ',' : '';
        $listDocParams = '{' . PHP_EOL
            . '    "page": 1, // 当前页' . PHP_EOL
            . '    "pagesize": 10' . $listDocParamsEndDh . ' // 单页条数' . PHP_EOL; // 分页列表文档参数
        if (!empty($realSearchList)) {
            $realSearchListNum = count($realSearchList);
            foreach ($realSearchList as $k => $v) {
                $queryType = ServiceClient::getInstance()->getQueryType($columnList[$v]['type']);
                $hasS = 'between' === $queryType ? 's' : '';
                $key = "search_{$v}{$hasS}";
                if ('s' === $hasS) {
                    $value = [];
                    $docValue = '[]';
                } else {
                    $value = '';
                    $docValue = '""';
                }
                $listParams[$key] = $value;
                $isEnd = $k === $realSearchListNum - 1;
                $dh = !$isEnd ? ',' : '';
                $listDocParams .= "    \"{$key}\": {$docValue}{$dh} // 搜索--{$columnList[$v]['comment']}" . PHP_EOL;
            }
        }
        $listParams = json_encode($listParams, JSON_UNESCAPED_UNICODE);
        $listDocParams .= '}';
        $msg = '添加/编辑参数:' . PHP_EOL
            . $actionParams . PHP_EOL
            . '分页列表参数:' . PHP_EOL
            . $listParams . PHP_EOL;
        $doc = $params['doc'];
        if ($doc) { // 有json注释
            $msg .= '添加/编辑文档参数:' . PHP_EOL
                . $actionDocParams . PHP_EOL
                . '分页列表文档参数:' . PHP_EOL
                . $listDocParams;
        }
        return $msg;
    }

    // 获取apifox接口调试参数
    public function getApifoxRequestParams($params = [])
    {
        $tableName = $params['name'] ?? '';
        if (empty($tableName)) {
            return $this->error('表名称不能为空');
        }
        $search = $params['search'] ?? '';
        $columns = $this->getTableColumns($tableName);
        $filterFields = ValidatorClient::getInstance()->getFilterFields();
        $actionParams = [ // 添加/编辑参数
            'type' => 'object',
            'properties' => [], // 属性列表
            'x-apifox-orders' => [], // apifox字段排序
            'required' => [], // 必传字段
        ];
        $listParams = [ // 分页列表参数
            'type' => 'object',
            'properties' => [
                'page' => [
                    'type' => 'integer',
                    'title' => '当前页',
                    'mock' => [
                        'mock' => 1,
                    ],
                ],
                'pagesize' => [
                    'type' => 'integer',
                    'title' => '单页条数',
                    'mock' => [
                        'mock' => 10,
                    ],
                ],
            ], // 属性列表
            'x-apifox-orders' => [ // apifox字段排序
                'page',
                'pagesize',
            ],
            'required' => [ // 必传字段
                'page',
                'pagesize',
            ],
        ];
        $searchList = explode(',', $search);
        $columnList = [];
        foreach ($columns as $column) {
            $name = $column->getName();
            $comment = $column->getComment();
            $type = $column->getType()->getName();
            $columnList[$name] = [
                'comment' => $comment,
                'type' => $type,
            ];
            if (in_array($name, $filterFields, true)) {
                continue;
            }
            [$title, $description] = TableLogicClient::getInstance()->getApifoxCommentList($comment);
            $actionParams['properties'][$name] = [
                'type' => $type,
                'title' => $title,
                'description' => $description,
            ];
            $actionParams['x-apifox-orders'][] = $name;
            $actionParams['required'][] = $name;
        }
        $actionParams = json_encode($actionParams, JSON_UNESCAPED_UNICODE);
        if (!empty($searchList)) {
            foreach ($searchList as $v) {
                if (!isset($columnList[$v])) {
                    continue;
                }
                $type = $columnList[$v]['type'];
                $comment = $columnList[$v]['comment'];
                [$title, $description] = TableLogicClient::getInstance()->getApifoxCommentList($comment);
                $listParams['properties'][$v] = [
                    'type' => $type,
                    'title' => "搜索--{$title}",
                    'description' => $description,
                ];
                $listParams['x-apifox-orders'][] = $v;
            }
        }
        $listParams = json_encode($listParams, JSON_UNESCAPED_UNICODE);

        return '添加/编辑参数:' . PHP_EOL
            . $actionParams . PHP_EOL
            . '分页列表参数:' . PHP_EOL
            . $listParams . PHP_EOL;
    }

    private function getTablePrefix()
    {
        return $this->config['prefix'];
    }

    // 获取配置
    private function getConfig()
    {
        return [
            'dbname' => $this->config['database'],
            'user' => $this->config['username'],
            'password' => $this->config['password'],
            'host' => $this->config['host'],
            'driver' => 'pdo_mysql',
        ];
    }

    // 获取指定表的字段
    private function getTableColumns($tableName = '')
    {
        if (empty($tableName)) {
            return $this->error('表名称不能为空');
        }
        $conn = DriverManager::getConnection($this->getConfig());
        $sm = $conn->getSchemaManager();
        $realTableName = $this->getTablePrefix() . $tableName;
        return $sm->listTableColumns($realTableName);
    }
}
